"""
传感器组件
"""
import typing
import json
from .framework import session_received, dispatch
from .base import BaseSession, BaseSessionParentType, BaseSessionType
from .utils import to_any, from_any, callback, Int32Value, FloatValue


@session_received
class Sensor(BaseSession):
    """
    传感器组件
    可以通过get_list来获取客户端设备所有支持的传感器列表
    使用register_listener来注册传感器的事件监听
    register_listener需要传递三个参数：
    第一个是需要监听的传感器Type，后面两个参数分别是传感器数值发生更改的回调函数以及精度改变的回调
    """

    name: typing.ClassVar[str] = "Sensor"

    TYPE_ANY: typing.ClassVar[int] = -1
    TYPE_ACCELEROMETER: typing.ClassVar[int] = 1
    TYPE_ORIENTATION: typing.ClassVar[int] = 3
    TYPE_LIGHT: typing.ClassVar[int] = 5
    TYPE_TEMPERATURE: typing.ClassVar[int] = 7
    TYPE_GRAVITY: typing.ClassVar[int] = 9
    TYPE_LINEAR_ACCELERATION: typing.ClassVar[int] = 10
    TYPE_AMBIENT_TEMPERATURE: typing.ClassVar[int] = 13

    # 采样频率
    SENSOR_DELAY_FASTEST: typing.ClassVar[int] = 0
    SENSOR_DELAY_GAME: typing.ClassVar[int] = 1
    SENSOR_DELAY_UI: typing.ClassVar[int] = 2
    SENSOR_DELAY_NORMAL: typing.ClassVar[int] = 3

    @classmethod
    async def create(cls: typing.Type[BaseSessionType], parent: BaseSessionParentType, *args: typing.Any,
                     **kwargs: typing.Dict) -> BaseSessionType:
        return await super().create(parent, *args, **kwargs)

    async def on_receive(self, msg):
        match msg.name:
            case 'onGetList':
                dispatch(self.on_get_list(msg.argv[0], session_id=msg.session, future_id=msg.future))
                return
            case 'onGetDefault':
                dispatch(self.on_get_default(msg.argv[0], session_id=msg.session, future_id=msg.future))
                return
            case _:
                await super().on_receive(msg)

    @callback(str)
    async def on_get_list(self, result, session_id, future_id):
        """
        当获取传感器列表成功，此方法被自动调用。
        通常不需要关注此方法的实现。
        """
        _list = json.loads(result)
        self.set_action_result(session_id, future_id, _list)

    async def get_list(self, _type: int = TYPE_ANY):
        """
        获取传感器列表
        """
        return await self.send_action_until_return('getList', to_any(_type, Int32Value))

    @callback(int)
    async def on_get_default(self, result, session_id, future_id):
        """
        当获取默认传感器成功，此方法被自动调用。
        通常不需要关注此方法的实现。
        """
        self.set_action_result(session_id, future_id, result)

    async def get_default(self, _type: int):
        """
        获取默认传感器
        返回值是传感器的Type Id, -1表示没有默认传感器
        """
        return await self.send_action_until_return('getDefault', to_any(_type, Int32Value))

    async def register_listener(self, _type: int,
                                sensor_cb: typing.Callable, accuracy_cb: typing.Callable,
                                samplingPeriodUs: int = SENSOR_DELAY_NORMAL):
        """
        注册传感器的监听函数
        :param _type: 传感器的Type
        :param sensor_cb: 传感器数值改变回调方法，方法签名需要带三个浮点数参数
        :param accuracy_cb: 传感器精度改变回调方法，方法签名需要带一个整形参数
        :param samplingPeriodUs: 采样频率
        """
        async def inner_1(f_1: float, f_2: float, f_3: float):
            await sensor_cb(from_any(f_1, FloatValue),
                            from_any(f_2, FloatValue),
                            from_any(f_3, FloatValue))

        async def inner_2(num: int):
            await accuracy_cb(from_any(num, Int32Value))

        dispatch(self.send_action('registerListener', to_any(_type, Int32Value),
                                  self.create_callback(inner_1), self.create_callback(inner_2),
                                  to_any(samplingPeriodUs)))

    async def unregister_listener(self):
        """取消监听"""
        dispatch(self.send_action('unregisterListener'))